package com.base.balibrary.utils;

import android.app.Activity;
import android.view.View;

import com.base.balibrary.ioc.BaseContentView;
import com.base.balibrary.ioc.BaseEvent;
import com.base.balibrary.ioc.BaseViewInject;
import com.base.balibrary.ioc.DynamicHandler;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Objects;

/**
 * BAndroid
 * Created by YichenZ on 2015/7/23 10:23.
 * thanks blog http://blog.csdn.net/lmj623565791/article/details/39269193
 */
public class ViewInjectUtil {

    private static final String METHOD_SET_CONTENT_VIEW="setContentView";
    private static final String METHOD_FIND_VIEW_BY_ID="findViewById";

    static Class<? extends Activity> clazz;
    //是否注入过view
    private static boolean isView=false;

    public static void inject(Activity activity){
        clazz=activity.getClass();
        injectContentView(activity);
    }

    /**
     * 注入布局
     * @param activity
     */
    private static void injectContentView(Activity activity){
        //查询是否存在BaseContentView注解
        BaseContentView baseContentView=clazz.getAnnotation(BaseContentView.class);
        if(baseContentView!=null){
            try {
                //获得layoutId值
                int contentViewLayoutId = baseContentView.value();
                //获得加载layout方法以及参数类型
                Method method = clazz.getMethod(METHOD_SET_CONTENT_VIEW,int.class);
                //开启语言访问检查
                method.setAccessible(true);
                //调用方法
                method.invoke(activity, contentViewLayoutId);

                injectView(activity);
            } catch (Exception  e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 注入Views
     * @param activity
     */
    private static void injectView(Activity activity){
        //获得所有的声明字段
        Field[] fields =clazz.getDeclaredFields();
        for (Field field : fields){
            BaseViewInject viewInjectAnnotation =field.getAnnotation(BaseViewInject.class);
            if(viewInjectAnnotation!=null){
                if(!isView)
                    isView=true;
                int viewId=viewInjectAnnotation.value();

                if(viewId!=-1){
                    try{
                        Method method =clazz.getMethod(METHOD_FIND_VIEW_BY_ID,int.class);
                        Object resView =method.invoke(activity,viewId);
                        field.setAccessible(true);
                        field.set(activity,resView);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }
        //只在注入过view后才执行onClick注入
        if(isView)
            injectEvents(activity);
    }

    private static void injectEvents(Activity activity){
        //获得所有的method
        Method[] methods =clazz.getMethods();
        for(Method method : methods ){
            //获得方法中注解
            Annotation[] annotations =method.getAnnotations();
            for(Annotation annotation : annotations){
                //获得注解中的注解
                Class<? extends Annotation> annotationType=annotation.annotationType();
                //判断是否有EventBase注解
                BaseEvent eventBase =annotationType.getAnnotation(BaseEvent.class);
                if(eventBase!=null){
                    String listenerSetter =eventBase.listenerSetter();
                    Class<?> listenerType=eventBase.listenerType();
                    String methodName=eventBase.methodName();
                    try{
                        Method aMethod = annotationType.getDeclaredMethod("value");
                        int[] valueIds =(int[]) aMethod.invoke(annotation,new Object[0]);//new Object[0] 可以为null，会报异常但可以通过编译
                        DynamicHandler handler =new DynamicHandler(activity);
                        handler.addMethod(methodName,method);
                        Object listener = Proxy.newProxyInstance(listenerType.getClassLoader(),new Class<?>[]{listenerType},handler);
                        for (int viewId : valueIds){
                            View view=activity.findViewById(viewId);
                            Method setEventListenerMethod =view.getClass().getMethod(listenerSetter,listenerType);
                            setEventListenerMethod.invoke(view,listener);
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }


    }

}
